import Cesium from '../Ces/Cesium'
import AWXParser from '../Module/AWXParser'
import M4Parser from '../Module/micaps4/M4Parser'
import W3DParser from '../Module/W3DParser'
import WeDataParserBase from './WeDataParserBase'

class WeDataProviderRequest {
  getUrlCallback
  timeSampleArray
  currentIndex = -1
  parser: WeDataParserBase
  requestData
  requestCaches
  clampAnime: boolean
  constructor(options) {
    this.getUrlCallback = options.getUrlCallback
    this.timeSampleArray = options.timeSampleArray

    let parser = options.parser;

    if (parser && typeof parser === 'string') {
      if (parser === 'awx') {
        parser = new AWXParser()
      } else if (parser === 'm4') {
        parser = new M4Parser()
      } else if (parser === 'w3d') {
        parser = new W3DParser()
      }
    }

    this.parser = parser || new WeDataParserBase()

    this.requestData = [
      {
        url: options.url,
        time: undefined,
      },
    ]

    this.requestCaches = [
      {
        url: '',
      },
    ]

    if (this.timeSampleArray) {
      if (!options.url) {
        this.requestData[0].url = this.timeSampleArray._urls[0]
      }
      this.clampAnime = options.clampAnime ?? true
      if (this.clampAnime) {
        this.requestData.push({
          url: '',
          time: undefined,
        })
        this.requestCaches.push({
          url: '',
        })
      }
    }
  }

  loadCustom() {
    const { parser } = this
    const promise1 = parser.requestCustom1 ? parser.requestCustom1() : Promise.resolve(null)
    const promise2 = parser.requestCustom2 ? parser.requestCustom2() : Promise.resolve(null)
    return Promise.all([
      promise1,
      promise2]).then((res) => {
        return res
      })
  }

  loadData() {
    const urls = []
    const promise = new Promise((resovle) => {
      const promises = []
      const requestData = this.requestData
      requestData.forEach((data) => {
        const { url } = data
        if (Cesium.defined(url) && url !== '') {
          promises.push(this.getOrRequest(url))
          urls.push(url)
        }
      })

      return Promise.all(promises).then((images) => {
        const caches = this.requestCaches
        for (let i = 0; i < images.length; i++) {
          caches[i] = images[i]
          caches[i].url = urls[i]
          if (Cesium.defined(this.timeSampleArray) && this.currentIndex > -1) {
            requestData[i].time = this.timeSampleArray.getTime(this.currentIndex + i)
          }
        }
        if (images.length === 2) {
          const tmp = images[0]
          images[0] = images[1]
          images[1] = tmp
        }
        resovle(images)
      }).catch(() => {
        const errors = `${requestData[0].url},${requestData[1]?.url}`
        throw new Cesium.RuntimeError(`${errors} WeDataProviderRequest get fail.`)
      })
    })

    return promise;
  }

  getOrRequest(url) {
    const caches = this.requestCaches

    for (let i = 0; i < caches.length; i++) {
      const cache = caches[i]

      if (cache.url === url) {
        return Promise.resolve(cache)
      }
    }

    return this.parser.requestImage(url, this.getUrlCallback)
  };

  updateTimeData(frameState) {
    let dirty = false

    const timeSampleArray = this.timeSampleArray;

    const idx = timeSampleArray.getIndex(frameState.time)

    if (this.currentIndex !== idx) {
      this.currentIndex = idx;
      for (let i = 0; i < this.requestData.length; i++) {
        const url = timeSampleArray.getUrl(idx + i)
        this.requestData[i].url = url
      }
      dirty = true
    }

    return dirty
  }

  getAnimeStep(frameState) {
    const time0 = this.requestData[0].time
    const time1 = this.requestData[1].time

    if (Cesium.defined(time1)) {
      const range = Cesium.JulianDate.secondsDifference(time1, time0)
      const offset = Cesium.JulianDate.secondsDifference(frameState.time, time0)
      return Cesium.Math.clamp(offset / range, 0.0, 1.0)
    }

    return 0
  }
}



export default WeDataProviderRequest;
